﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Diagnostics;

namespace Slippor.Common.PluginFramework
{
    public interface IVersion
    {
        Version Version { get; }
        String Description { get; }
        bool IsVersionable { get; }

        void GetLatestVersionAsync();
        event EventHandler<PluginVersionEventArgs> GetLatestVersionCompleted;
        void UpdateAsync();
        event EventHandler<UpdateEventArgs> UpdateCompleted;
    }

    public class BasicVersion:IVersion
    {
        Version _version;
        public BasicVersion(String versionMark)
        {
            _version = new Version(versionMark);
        }

        public bool IsVersionable
        {
            get { return false; }
        }

        #region IVersion Members

        public Version Version
        {
            get { return _version; }
        }

        public string Description
        {
            get { return String.Empty; }
        }

        public void GetLatestVersionAsync()
        {
            ;
        }

        public event EventHandler<PluginVersionEventArgs> GetLatestVersionCompleted;

        public virtual void UpdateAsync()
        {
            ;
        }

        public event EventHandler<UpdateEventArgs> UpdateCompleted;

        #endregion
    }

    public abstract class AbstractVersion : IVersion
    {
        Version _version;
        public AbstractVersion(String versionMark)
        {
            _version = new Version(versionMark);
        }

        public bool IsVersionable
        {
            get { return true; }
        }

        #region IVersion Members

        public Version Version
        {
            get { return _version; }
        }

        public string Description
        {
            get { return String.Empty; }
        }

        protected abstract string key
        {
            get;
        }

        private readonly String _url = "http://www.box.net/shared/ghlicb7d21";
        private PluginVersion GetVersion()
        {
            String pattern = String.Format(@">\W*{0}::ver=(?<ver>[\d\.]+)##des=(?<des>[^<]*)<", key);
            return PluginUtility.GetVersion(_url, pattern, "ver", "des");
        }

        public void GetLatestVersionAsync()
        {
            using (BackgroundWorker worker = new BackgroundWorker())
            {
                worker.DoWork += (sender, e) =>
                {
                    e.Result = GetVersion();
                };
                worker.RunWorkerCompleted += (sender, e) =>
                    {
                        PluginVersion version = e.Result as PluginVersion;
                        if (GetLatestVersionCompleted != null)
                        {
                            GetLatestVersionCompleted(this, new PluginVersionEventArgs() { Succeed = (version != null), Version = version });
                        }
                    };
                worker.RunWorkerAsync();
            }
        }

        public event EventHandler<PluginVersionEventArgs> GetLatestVersionCompleted;

        protected abstract string downloadUrl
        {
            get;
        }

        public virtual void UpdateAsync()
        {
            using (BackgroundWorker worker = new BackgroundWorker())
            {
                worker.DoWork += (sender, e) =>
                {
                    Process.Start(downloadUrl);

                };
                worker.RunWorkerCompleted += (sender, e) =>
                    {
                        if (UpdateCompleted != null)
                        {
                            UpdateCompleted(this, new UpdateEventArgs() { Succeed = downloadUrl != null });
                        }
                    };
                worker.RunWorkerAsync();
            }
        }

        public event EventHandler<UpdateEventArgs> UpdateCompleted;

        #endregion
    }

    public sealed class PluginVersionEventArgs:EventArgs
    {
        public bool Succeed
        {
            get;
            set;
        }

        public Exception Error
        {
            get;
            set;
        }

        public PluginVersion Version
        {
            get;
            set;
        }
    }

    public sealed class UpdateEventArgs : EventArgs
    {
        public bool Succeed
        {
            get;
            set;
        }

        public Exception Error
        {
            get;
            set;
        }
    }

    public class PluginVersion
    {
        public Version Version { get; set; }
        public String Description { get; set; }
    }
}
